const net = require('net');
const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');

// 工具函数：格式化时间为 yy-mm-dd hh:ii:ss
function getFormattedTime() {
    const date = new Date();
    const year = date.getFullYear().toString().slice(2); // 取后两位年份
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');
    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

// 配置参数
const config = {
    port: 3000,
    publicDir: path.join(__dirname, 'public'),
    routesPath: path.join(__dirname, 'routes.json'),
    keepAliveTimeout: 30000, // 连接保持超时（30秒）
    maxKeepAliveRequests: 5,  // 最大复用次数
    pollInterval: 10 // 轮询间隔（毫秒）
};

// 初始化服务器所需文件和目录
async function initializeServer() {
    // 创建public目录
    if (!fsSync.existsSync(config.publicDir)) {
        await fs.mkdir(config.publicDir);
    }

    // 创建默认页面文件
    const defaultFiles = [
        { name: 'index.html', content: '<h1>首页</h1><p>欢迎访问我的服务器</p>' },
        { name: 'about.html', content: '<h1>关于页面</h1><p>这是一个简单的HTTP服务器</p>' },
        { name: 'contact.html', content: '<h1>联系页面</h1><p>联系方式：example@test.com</p>' },
        { name: '404.html', content: '<h1>404 页面未找到</h1>' }
    ];

    for (const file of defaultFiles) {
        const filePath = path.join(config.publicDir, file.name);
        if (!fsSync.existsSync(filePath)) {
            await fs.writeFile(filePath, file.content);
        }
    }

    // 创建默认路由配置（确保根路径"/"正确映射）
    if (!fsSync.existsSync(config.routesPath)) {
        await fs.writeFile(config.routesPath, JSON.stringify({
            '/': 'index.html', // 根路径正确映射到index.html
            '/about': 'about.html',
            '/contact': 'contact.html',
            '/index.html': 'index.html'
        }, null, 2));
    }
}

// 路由处理类
class RouteHandler {
    constructor() {
        this.routes = {};
        this.loadRoutes();
    }

    async loadRoutes() {
        try {
            const routeData = await fs.readFile(config.routesPath, 'utf8');
            this.routes = JSON.parse(routeData);
            // 打印所有加载的路由
            console.log('\n===== 加载的路由配置 =====');
            Object.entries(this.routes).forEach(([path, file]) => {
                console.log(`${path} → ${file}`);
            });
            console.log('==========================\n');
        } catch (err) {
            console.error(`[${getFormattedTime()}] 加载路由配置失败:`, err.message);
            this.routes = { '/': 'index.html' }; //  fallback默认路由
        }
    }

    getFilePath(requestPath) {
        // 处理网站图标请求
        if (requestPath === '/favicon.ico') {
            return 'favicon';
        }

        // 规范化路径
        let normalizedPath = requestPath;
        // 保留根路径原样，其他路径移除末尾斜杠
        if (normalizedPath !== '/' && normalizedPath.endsWith('/')) {
            normalizedPath = normalizedPath.slice(0, -1);
        }

        // 查找对应的文件
        const fileName = this.routes[normalizedPath];
        return fileName ? path.join(config.publicDir, fileName) : null;
    }
}

// 连接管理类
class ConnectionManager {
    constructor() {
        this.connections = new Map();
        this.nextConnectionId = 1;
    }

    addConnection(socket) {
        const connectionId = this.nextConnectionId++;
        // 设置超时计时器
        const timeoutTimer = setTimeout(() => {
            this.closeConnection(connectionId, '超时');
        }, config.keepAliveTimeout);

        this.connections.set(connectionId, {
            socket,
            buffer: Buffer.alloc(0),
            status: 'reading',
            timeoutTimer,
            startTime: new Date(),
            requestCount: 0 // 记录复用次数
        });

        console.log(`[${getFormattedTime()}] 客户端连接 [id: ${connectionId}]`);
        return connectionId;
    }

    getConnection(connectionId) {
        return this.connections.get(connectionId);
    }

    updateConnection(connectionId, data) {
        const connection = this.getConnection(connectionId);
        if (connection) {
            // 重置超时计时器
            clearTimeout(connection.timeoutTimer);
            connection.timeoutTimer = setTimeout(() => {
                this.closeConnection(connectionId, '超时');
            }, config.keepAliveTimeout);

            this.connections.set(connectionId, { ...connection, ...data });
        }
    }

    closeConnection(connectionId, reason = '正常关闭') {
        const connection = this.getConnection(connectionId);
        if (connection) {
            clearTimeout(connection.timeoutTimer);
            connection.socket.end();
            this.connections.delete(connectionId);
            const duration = Math.round((new Date() - connection.startTime) / 1000);

            // 优化日志显示
            let logMessage = `[${getFormattedTime()}] 客户端关闭 [id: ${connectionId}]`;
            if (reason === '超时' && connection.buffer.length === 0 && connection.requestCount === 0) {
                logMessage += ` 原因: 空闲连接超时 (浏览器预连接，正常行为)`;
            } else {
                logMessage += ` 原因: ${reason}`;
            }
            logMessage += ` (持续 ${duration}秒，处理请求: ${connection.requestCount}次)`;

            console.log(logMessage);
        }
    }

    getAllConnectionIds() {
        return Array.from(this.connections.keys());
    }
}

// HTTP服务器类
class SimpleHttpServer {
    constructor() {
        this.server = null;
        this.routeHandler = new RouteHandler();
        this.connectionManager = new ConnectionManager();
    }

    async start() {
        try {
            await initializeServer();
            this.server = net.createServer(socket => this.handleNewConnection(socket));

            this.server.listen(config.port, () => {
                console.log(`[${getFormattedTime()}] 服务器启动成功，监听端口: ${config.port}`);
                console.log(`[${getFormattedTime()}] 支持连接复用，超时时间: ${config.keepAliveTimeout/1000}秒`);
                this.startPolling();
            });
        } catch (err) {
            console.error(`[${getFormattedTime()}] 服务器启动失败:`, err.message);
            process.exit(1);
        }
    }

    handleNewConnection(socket) {
        const connectionId = this.connectionManager.addConnection(socket);
        const connection = this.connectionManager.getConnection(connectionId);

        // 记录客户端IP和端口
        const clientAddress = socket.remoteAddress;
        const clientPort = socket.remotePort;
        console.log(`[${getFormattedTime()}] [id: ${connectionId}] 客户端地址: ${clientAddress}:${clientPort}`);

        // 处理接收到的数据
        socket.on('data', chunk => {
            const conn = this.connectionManager.getConnection(connectionId);
            if (conn) {
                conn.buffer = Buffer.concat([conn.buffer, chunk]);
                // 打印接收到的数据片段（前100字符）
                const dataPreview = chunk.toString().substring(0, 100).replace(/\r\n/g, ' ');
                console.log(`[${getFormattedTime()}] [id: ${connectionId}] 收到数据: ${dataPreview}...`);

                this.processRequest(connectionId).catch(err => {
                    console.error(`[${getFormattedTime()}] [id: ${connectionId}] 处理请求错误:`, err.message);
                    this.connectionManager.closeConnection(connectionId, '处理请求错误');
                });
            }
        });

        // 处理连接错误
        socket.on('error', err => {
            console.error(`[${getFormattedTime()}] [id: ${connectionId}] 客户端错误:`, err.message);
            this.connectionManager.closeConnection(connectionId, '连接错误');
        });

        // 处理连接关闭
        socket.on('close', () => {
            this.connectionManager.closeConnection(connectionId, '客户端主动断开');
        });
    }

    async processRequest(connectionId) {
        const connection = this.connectionManager.getConnection(connectionId);
        if (!connection || connection.status !== 'reading') return;

        // 检查是否接收到完整的HTTP请求头
        const requestData = connection.buffer.toString();
        const headerEndIndex = requestData.indexOf('\r\n\r\n');

        if (headerEndIndex !== -1) {
            // 提取完整请求头和剩余数据
            const requestHeader = requestData.substring(0, headerEndIndex + 4);
            const remainingData = requestData.substring(headerEndIndex + 4);

            // 更新请求计数
            connection.requestCount++;
            this.connectionManager.updateConnection(connectionId, {
                requestCount: connection.requestCount
            });

            connection.status = 'processing';
            const [requestLine] = requestHeader.split('\r\n');
            const [method, requestPath, httpVersion] = requestLine.split(' ');

            // 打印完整请求信息
            console.log(`[${getFormattedTime()}] [id: ${connectionId}] 完整请求: ${method} ${requestPath} ${httpVersion || ''}`);

            // 处理网站图标请求
            if (requestPath === '/favicon.ico') {
                const response = `HTTP/1.1 204 No Content\r\n` +
                    `Connection: Keep-Alive\r\n` +
                    `Keep-Alive: timeout=${config.keepAliveTimeout/1000}, max=${config.maxKeepAliveRequests - connection.requestCount}\r\n` +
                    `\r\n`;
                connection.socket.write(response, () => {
                    // 处理剩余数据，避免重复解析
                    const remainingBuffer = Buffer.from(remainingData);

                    // 判断是否还能继续复用
                    if (connection.requestCount >= config.maxKeepAliveRequests) {
                        this.connectionManager.closeConnection(connectionId, '达到最大复用次数');
                    } else {
                        // 重置状态为可读取，保留剩余数据
                        this.connectionManager.updateConnection(connectionId, {
                            status: 'reading',
                            buffer: remainingBuffer
                        });
                        console.log(`[${getFormattedTime()}] [id: ${connectionId}] 连接保持活跃，等待下一个请求`);
                    }
                });
                return;
            }

            // 处理普通请求
            let filePath = this.routeHandler.getFilePath(requestPath);
            let statusCode = 200;
            let contentType = 'text/html';

            // 处理404情况
            if (!filePath || !fsSync.existsSync(filePath)) {
                statusCode = 404;
                filePath = path.join(config.publicDir, '404.html');
                console.log(`[${getFormattedTime()}] [id: ${connectionId}] 路径未找到，返回404: ${requestPath}`);
            } else {
                console.log(`[${getFormattedTime()}] [id: ${connectionId}] 路径匹配成功: ${requestPath} → ${filePath}`);
                // 确定内容类型
                const fileExt = path.extname(filePath).toLowerCase();
                const mimeTypes = {
                    '.html': 'text/html',
                    '.css': 'text/css',
                    '.js': 'text/javascript',
                    '.png': 'image/png',
                    '.jpg': 'image/jpeg',
                    '.gif': 'image/gif',
                    '.ico': 'image/x-icon'
                };
                contentType = mimeTypes[fileExt] || 'application/octet-stream';
            }

            // 读取文件并发送响应
            try {
                const fileContent = await fs.readFile(filePath);
                // 决定是否保持连接
                const connectionHeader = connection.requestCount >= config.maxKeepAliveRequests
                    ? 'close'
                    : 'Keep-Alive';

                const response = `HTTP/1.1 ${statusCode} ${statusCode === 200 ? 'OK' : 'Not Found'}\r\n` +
                    `Content-Type: ${contentType}\r\n` +
                    `Content-Length: ${fileContent.length}\r\n` +
                    `Connection: ${connectionHeader}\r\n` +
                    (connectionHeader === 'Keep-Alive' ?
                        `Keep-Alive: timeout=${config.keepAliveTimeout/1000}, max=${config.maxKeepAliveRequests - connection.requestCount}\r\n` : '') +
                    `\r\n`;

                // 发送响应
                connection.socket.write(response, err => {
                    if (err) {
                        this.connectionManager.closeConnection(connectionId, '响应头发送失败');
                        return;
                    }

                    connection.socket.write(fileContent, () => {
                        // 处理剩余数据，避免重复解析
                        const remainingBuffer = Buffer.from(remainingData);

                        if (connectionHeader === 'close') {
                            this.connectionManager.closeConnection(connectionId, '达到最大复用次数');
                        } else {
                            // 重置状态为可读取，保留剩余数据
                            this.connectionManager.updateConnection(connectionId, {
                                status: 'reading',
                                buffer: remainingBuffer
                            });
                            console.log(`[${getFormattedTime()}] [id: ${connectionId}] 连接保持活跃，等待下一个请求`);
                        }
                    });
                });
            } catch (err) {
                console.error(`[${getFormattedTime()}] [id: ${connectionId}] 文件处理错误:`, err.message);
                this.connectionManager.closeConnection(connectionId, '文件处理错误');
            }
        }
    }

    startPolling() {
        setInterval(() => {
            this.connectionManager.getAllConnectionIds().forEach(connectionId => {
                const connection = this.connectionManager.getConnection(connectionId);
                if (connection && connection.status === 'reading' && connection.buffer.length > 0) {
                    this.processRequest(connectionId).catch(err => {
                        console.error(`[${getFormattedTime()}] [id: ${connectionId}] 轮询处理错误:`, err.message);
                    });
                }
            });
        }, config.pollInterval);
    }
}

// 启动服务器
const server = new SimpleHttpServer();
server.start();

// 处理服务器关闭
process.on('SIGINT', () => {
    console.log(`\n[${getFormattedTime()}] 服务器正在关闭...`);
    process.exit(0);
});
